package parser;

import java.util.ArrayList;
import java.util.List;

import entity.Column;
import entity.Database.DataType;
import storage.DataAccessManager;
import net.sf.jsqlparser.expression.AllComparisonExpression;
import net.sf.jsqlparser.expression.AnyComparisonExpression;
import net.sf.jsqlparser.expression.CaseExpression;
import net.sf.jsqlparser.expression.DateValue;
import net.sf.jsqlparser.expression.DoubleValue;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.ExpressionVisitor;
import net.sf.jsqlparser.expression.Function;
import net.sf.jsqlparser.expression.InverseExpression;
import net.sf.jsqlparser.expression.JdbcParameter;
import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.expression.NullValue;
import net.sf.jsqlparser.expression.Parenthesis;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.expression.TimeValue;
import net.sf.jsqlparser.expression.TimestampValue;
import net.sf.jsqlparser.expression.WhenClause;
import net.sf.jsqlparser.expression.operators.arithmetic.Addition;
import net.sf.jsqlparser.expression.operators.arithmetic.Concat;
import net.sf.jsqlparser.expression.operators.arithmetic.Division;
import net.sf.jsqlparser.expression.operators.arithmetic.Multiplication;
import net.sf.jsqlparser.expression.operators.arithmetic.Subtraction;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
import net.sf.jsqlparser.expression.operators.relational.Between;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.expression.operators.relational.ExistsExpression;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.GreaterThan;
import net.sf.jsqlparser.expression.operators.relational.GreaterThanEquals;
import net.sf.jsqlparser.expression.operators.relational.InExpression;
import net.sf.jsqlparser.expression.operators.relational.IsNullExpression;
import net.sf.jsqlparser.expression.operators.relational.ItemsListVisitor;
import net.sf.jsqlparser.expression.operators.relational.LikeExpression;
import net.sf.jsqlparser.expression.operators.relational.MinorThan;
import net.sf.jsqlparser.expression.operators.relational.MinorThanEquals;
import net.sf.jsqlparser.expression.operators.relational.NotEqualsTo;
import net.sf.jsqlparser.statement.insert.*;
import net.sf.jsqlparser.statement.select.SubSelect;

public class InsertParser implements ItemsListVisitor,ExpressionVisitor
{
	private String result;
	private String databaseName;
	private ArrayList<String> values;
	public InsertParser(String databaseName)
	{
		this.databaseName = databaseName;
	}
	
	public String insert(Insert insert)
	{
		DataAccessManager data = new DataAccessManager();
		entity.Table tableEntity = data.getDatabaseByName(databaseName).getTableByName(insert.getTable().getName());
		if (tableEntity==null) return "Insert error. Can not find table named "+insert.getTable().getName()+".";
		values = new ArrayList<String>();
		insert.getItemsList().accept(this);
		ArrayList<String> columnValues = new ArrayList<String>();
		for (int i=0;i<tableEntity.getColumnsCount();i++) columnValues.add("");
		if (insert.getColumns()==null) 
		{
			for (int i=0;i<values.size();i++) 
			{
				Column column = tableEntity.getColumnAt(i);
				if (column.getType()==DataType.Int)
				{
					try
					{
						int n = Integer.parseInt(values.get(i));
					}
					catch (NumberFormatException NFE)
					{
						return "Insert error. Insert string into int type column.";
					}
					
				}
				columnValues.set(i, values.get(i));
				
			}
			if (!tableEntity.addRow(columnValues)) return "Insert error. Blank or duplicate primary key column.";
		}
		else 
		{
			for (int i=0;i<insert.getColumns().size();i++)
			{
				Column column = tableEntity.getColumnByName(insert.getColumns().get(i).toString());
				if (column==null) return "Insert error. Can not find column "+insert.getColumns().get(i).toString();
				if (column.getType()==DataType.Int)
				{
					try
					{
						int n = Integer.parseInt(values.get(i));
					}
					catch (NumberFormatException NFE)
					{
						return "Insert error. Insert string into int type column.";
					}
					
				}
				columnValues.set(tableEntity.getColumnIndexByName(column.getName()), values.get(i));
			}
			if (!tableEntity.addRow(columnValues)) return "Insert error. Blank or duplicate primary key column.";
		}
		if (tableEntity.getPrimaryKey()!=-1)
			if (tableEntity.getColumnAt(tableEntity.getPrimaryKey()).getDataAt(tableEntity.getRowCount())==null) return "Insert error. Blank primary key column.";
		data.saveDatabases();
		return new String("Insert successfully.");
	}

	@Override
	public void visit(SubSelect subSelect) 
	{
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(ExpressionList expressionList) 
	{
		List<Expression> expressions = expressionList.getExpressions();
		for (int i=0;i<expressions.size();i++) expressions.get(i).accept(this);
		
	}

	@Override
	public void visit(NullValue arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(Function arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(InverseExpression arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(JdbcParameter arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(DoubleValue arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(LongValue longValue) 
	{
		values.add(longValue.getStringValue());
		
	}

	@Override
	public void visit(DateValue arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(TimeValue arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(TimestampValue arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(Parenthesis arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(StringValue stringValue) 
	{
		values.add(stringValue.getValue());
	}

	@Override
	public void visit(Addition arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(Division arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(Multiplication arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(Subtraction arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(AndExpression arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(OrExpression arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(Between arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(EqualsTo arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(GreaterThan arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(GreaterThanEquals arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(InExpression arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(IsNullExpression arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(LikeExpression arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(MinorThan arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(MinorThanEquals arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(NotEqualsTo arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(net.sf.jsqlparser.schema.Column column) 
	{
		values.add(column.getColumnName());
		
	}

	@Override
	public void visit(CaseExpression arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(WhenClause arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(ExistsExpression arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(AllComparisonExpression arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(AnyComparisonExpression arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(Concat arg0) {
		// TODO Auto-generated method stub
		
	}

}
